package com.csust.automaticteach.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csust.automaticteach.app.teacher.ExamGenerateApp;
import com.csust.automaticteach.constant.OrderConstant;
import com.csust.automaticteach.exception.BusinessException;
import com.csust.automaticteach.exception.ErrorCode;
import com.csust.automaticteach.exception.ThrowUtils;
import com.csust.automaticteach.model.dto.generateexam.AddGenerateExamForAiRequest;
import com.csust.automaticteach.model.dto.generateexam.AddGenerateExamRequest;
import com.csust.automaticteach.model.dto.generateexam.GenerateExamQueryDTO;
import com.csust.automaticteach.model.entity.*;
import com.csust.automaticteach.model.vo.generateexam.GenerateExamPageVO;
import com.csust.automaticteach.model.vo.generateexam.GenerateExamResponse;
import com.csust.automaticteach.model.vo.generateexam.GenerateExamVO;
import com.csust.automaticteach.model.vo.generateteach.UploadReturnVO;
import com.csust.automaticteach.service.*;
import com.csust.automaticteach.mapper.GenerateExamMapper;
import com.csust.automaticteach.utils.FileReaderUtil;
import com.csust.automaticteach.utils.ParseGenerateExerciseJsonUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import static cn.hutool.json.JSONUtil.toJsonStr;
import static com.csust.automaticteach.constant.ExceptionConstant.ONLY_ONE_REFERENCE_ALLOWED;
import static com.csust.automaticteach.constant.ExceptionConstant.SYSTEM_ERROR;
import static com.csust.automaticteach.constant.FileConstant.FILE_TYPE_ERROR;
import static com.csust.automaticteach.constant.StatusConstant.WAITING;

/**
* @author 钰玟
* @description 针对表【t_generate_exam(测试生成)】的数据库操作Service实现
* @createDate 2025-07-07 19:24:32
*/
@Service
@Slf4j
public class GenerateExamServiceImpl extends ServiceImpl<GenerateExamMapper, GenerateExam>
    implements GenerateExamService{
    @Resource
    private FileReaderUtil fileReaderUtil;
    @Resource
    private GenerateTeachService generateTeachService;
    @Resource
    private ExamGenerateApp examGenerateApp;
    @Resource
    private ParseGenerateExerciseJsonUtil parseGenerateExerciseJsonUtil;
    @Resource
    private ExercisesService exercisesService;
    @Resource
    private ExercisesSetsService exercisesSetsService;
    @Resource
    private SetExercisesService setExercisesService;

    //TODO
    @Override
    @Deprecated //无需后端解析上传的文件
    public UploadReturnVO uploadReferenceFile(MultipartFile file, User loginUser) {
        //判断文件类型
        String filename = file.getOriginalFilename();
        if (!(filename.endsWith(".doc") || filename.endsWith(".docx") || filename.endsWith(".pdf"))) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR,FILE_TYPE_ERROR);
        }
        String fileType = null;
        if (filename.contains(".")) {
            fileType = filename.substring(filename.indexOf(".") + 1);
        }
        // Read file content
        List<String> content = new ArrayList<>();
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            content = fileReaderUtil.readFile(inputStream, fileType);
        } catch (Exception e) {
            log.error("Error reading file: {}", e.getMessage());
            throw new BusinessException(ErrorCode.OPERATION_ERROR,SYSTEM_ERROR);
        }
        //得到参考资料
        String context = String.join("\n", content);

        GenerateExam generateExam = new GenerateExam();
        generateExam.setStatus(WAITING);//状态
        String title = loginUser.getUserName() + "的教学测试";//标题
        generateExam.setTitle(title);
        generateExam.setReference(context);//参考材料
        generateExam.setUserId(loginUser.getId());//所属用户
        //插入数据库
        boolean save = this.save(generateExam);
        if(!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,SYSTEM_ERROR);
        }
        //设置响应
        UploadReturnVO uploadReturnVO = new UploadReturnVO();
        //主键回显
        uploadReturnVO.setId(generateExam.getId());
        return uploadReturnVO;
    }
    @Override
    public List<Exercises> addGenerateExamSynRefactoring (AddGenerateExamRequest addGenerateExamRequest, User user) {
        //1.获取相关数据
        //1.1 获取用户id
        Long userId = user.getId();
        //1.2 得到 reference
        AddGenerateExamForAiRequest addGenerateExamForAiRequest = getReferenceByRequest(addGenerateExamRequest);
        //1.3 题目+题型
        addGenerateExamForAiRequest.setExams(addGenerateExamRequest.getExams());//题目+题型
        //1.4 难度
        String difficulty = addGenerateExamRequest.getDifficultyLevel();//
        addGenerateExamForAiRequest.setDifficultyLevel(difficulty);
        //2. 生成测试
        String chatId = UUID.randomUUID().toString();
        String result = examGenerateApp.doGenerate(addGenerateExamForAiRequest, chatId);
        //3. 解析content 成为一个数组列表
        List<GenerateExamResponse> generateExamResponseList = parseGenerateExerciseJsonUtil.parseJson(result, GenerateExamResponse.class);
        //4.得到题目列表
        String title = user.getUserName() + "老师的教学测试";
        List<Exercises> exercisesList = generateExamResponseList.stream().map(generateExamResponse -> {
            Exercises exercises = new Exercises();
            BeanUtils.copyProperties(generateExamResponse, exercises);
            List<String> options = generateExamResponse.getOptions();
            List<String> knowledgePoints = generateExamResponse.getKnowledgePoints();
            exercises.setOptions(toJsonStr(options));//选项
            exercises.setKnowledgePoint(knowledgePoints.get(0));//知识点
            exercises.setUserId(userId);//用户Id
            exercises.setDifficulty(difficulty);//难度
            exercises.setTitle(title+"题");//难度
            return exercises;
        }).toList();
        //插入数据库
        boolean saved1 = exercisesService.saveBatch(exercisesList);
        //5. 组成套题
        //组成套题
        ExercisesSets exercisesSets = ExercisesSets.builder().title(title).userId(userId).build();
        boolean saved2 = exercisesSetsService.save(exercisesSets);
        //组成套题的关联
        List<SetExercises> setExercisesList = setExercisesService.getSetExercisesList(exercisesList, exercisesSets.getId());
        boolean saved3 = setExercisesService.saveBatch(setExercisesList);
        ThrowUtils.throwIf(!saved1 || !saved2 || !saved3, ErrorCode.OPERATION_ERROR);
        return exercisesList;
    }
    @Override
    public AddGenerateExamForAiRequest getReferenceByRequest(AddGenerateExamRequest addGenerateExamRequest) {
        //1.1 生成测试Id  已改为 前端上传文件直接解析
//        Long id = addGenerateExamRequest.getId();
        Long id = 1L;//保证不报错
        //1.2 大纲id
        Long generateTeachId = addGenerateExamRequest.getGenerateTeachId();
        //1.3 知识点
        String knowledgePoint = addGenerateExamRequest.getKnowledgePoint();
        AddGenerateExamForAiRequest addGenerateExamForAiRequest = new AddGenerateExamForAiRequest();
        //region
        if(ObjUtil.isNotNull(id)){
            //则选择的是自主提供的参考材料
            GenerateExam generateExam = this.getById(id);
            String reference = generateExam.getReference();
            //设置参考材料
            addGenerateExamForAiRequest.setReference(reference);
        }
        if(generateTeachId !=null){
            GenerateTeach generateTeach = generateTeachService.getById(generateTeachId);
            //选择的是已有的课程大纲
            String courseOutline = generateTeach.getContent();
            if(addGenerateExamForAiRequest.getReference()!=null&& addGenerateExamForAiRequest.getReference().isEmpty()){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(courseOutline);
        }
        if(StrUtil.isNotBlank(knowledgePoint)){
            //选择的是知识点
            if(addGenerateExamForAiRequest.getReference()!=null&& addGenerateExamForAiRequest.getReference().isEmpty()){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(knowledgePoint);
        }
        return addGenerateExamForAiRequest;
    }

    @Override
    public List<GenerateExamVO> addGenerateExamSyn(AddGenerateExamRequest addGenerateExamRequest, User user) {
        //1.1 生成测试Id  已改为 前端上传文件直接解析
//        Long id = addGenerateExamRequest.getId();
        Long id = 1L;//保证不报错
        //大纲id
        Long generateTeachId = addGenerateExamRequest.getGenerateTeachId();
        //知识点
        String knowledgePoint = addGenerateExamRequest.getKnowledgePoint();
        AddGenerateExamForAiRequest addGenerateExamForAiRequest = new AddGenerateExamForAiRequest();
        if(ObjUtil.isNotNull(id)){
            //则选择的是自主提供的参考材料
            GenerateExam generateExam = this.getById(id);
            String reference = generateExam.getReference();
            //设置参考材料
            addGenerateExamForAiRequest.setReference(reference);
        }

        if(generateTeachId !=null){
            GenerateTeach generateTeach = generateTeachService.getById(generateTeachId);
            //选择的是已有的课程大纲
            String courseOutline = generateTeach.getContent();
            if(addGenerateExamForAiRequest.getReference()!=null&&"".equals(addGenerateExamForAiRequest.getReference())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(courseOutline);
        }
        if(StrUtil.isNotBlank(knowledgePoint)){
            //选择的是知识点
            if(addGenerateExamForAiRequest.getReference()!=null&&"".equals(addGenerateExamForAiRequest.getReference())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(knowledgePoint);
        }
        addGenerateExamForAiRequest.setExams(addGenerateExamRequest.getExams());
        addGenerateExamForAiRequest.setDifficultyLevel(addGenerateExamRequest.getDifficultyLevel());
        String chatId = UUID.randomUUID().toString();
        String content = examGenerateApp.doGenerate(addGenerateExamForAiRequest, chatId);
        // The test
//        String content = "[ { \"topic\": \"网络原理综合设计\", \"type\": \"选择题\", \"content\": \"在Socket编程中，以下关于服务器端操作的正确描述是：\", \"options\": [ \"A. 服务器端无需绑定端口号即可接收客户端请求\", \"B. 每个客户端连接必须创建新线程独立处理\", \"C. 可以通过同一个Socket对象同时处理多个客户端请求\", \"D. 服务器必须先启动并监听指定端口\" ], \"answer\": \"D\", \"explanation\": \"服务器必须先绑定端口并进入监听状态（D正确）。A错误，服务器需要绑定端口；B错误，可用线程池或IO复用技术；C错误，普通Socket只能处理单连接\", \"knowledgePoints\": [\"Socket编程基础\", \"服务器配置\"] }, { \"topic\": \"网络原理综合设计\", \"type\": \"选择题\", \"content\": \"关于TCP和UDP协议的特性，正确的是：\", \"options\": [ \"A. TCP提供可靠传输但不保证顺序交付\", \"B. UDP支持多播且具有拥塞控制机制\", \"C. TCP连接建立需要三次握手\", \"D. UDP头部包含16位校验和字段\" ], \"answer\": \"C\", \"explanation\": \"TCP三次握手建立连接（C正确）。A错误，TCP保证顺序交付；B错误，UDP无拥塞控制；D错误，UDP校验和为可选字段\", \"knowledgePoints\": [\"传输层协议\", \"网络通信原理\"] }, { \"topic\": \"网络原理综合设计\", \"type\": \"选择题\", \"content\": \"在实现客户端-服务器架构时，以下哪项属于服务器端必须实现的功能？\", \"options\": [ \"A. 动态生成HTML页面\", \"B. 处理并发请求\", \"C. 解析HTTP请求头\", \"D. 维护会话状态\" ], \"answer\": \"B\", \"explanation\": \"服务器端需处理并发请求（B正确）。A/C/D为Web服务器特有功能，而通用服务器可能不需要\", \"knowledgePoints\": [\"网络架构设计\", \"并发处理\"] }, { \"topic\": \"网络原理综合设计\", \"type\": \"选择题\", \"content\": \"进行网络应用测试时，以下哪个工具最适合抓取和分析网络数据包？\", \"options\": [ \"A. Wireshark\", \"B. JUnit\", \"C. Valgrind\", \"D. GDB\" ], \"answer\": \"A\", \"explanation\": \"Wireshark是专用网络协议分析工具（A正确）。B是单元测试框架，C/D是内存调试工具\", \"knowledgePoints\": [\"网络测试工具\", \"数据包分析\"] }, { \"topic\": \"网络原理综合设计\", \"type\": \"选择题\", \"content\": \"在撰写网络应用测试报告时，必须包含以下哪项内容？\", \"options\": [ \"A. 网络设备的品牌型号\", \"B. 代码行覆盖率数据\", \"C. 不同负载下的响应时间\", \"D. 开发人员工作日志\" ], \"answer\": \"C\", \"explanation\": \"性能测试需记录不同负载的响应时间（C正确）。A/B/D属于非必要信息\", \"knowledgePoints\": [\"测试报告规范\", \"性能评估\"] } ]";
        //TODO 异步化
        //入库数据
        GenerateExam generateExam = new GenerateExam();
        if(id!=null) {
            generateExam.setId(id);
        }
        String title = user.getUserName() + "的教学测试";//标题
        generateExam.setTitle(title);
//        generateExam.setContent(content);
        generateExam.setUserId(user.getId());
        generateExam.setGenerateTeachId(generateTeachId);
        generateExam.setKnowledgePoint(knowledgePoint);
        generateExam.setDifficultyLevel(addGenerateExamRequest.getDifficultyLevel());
        generateExam.setStatus(1);//草稿

        //解析content 成为一个数组列表
        List<GenerateExamResponse> generateExamResponseList = parseGenerateExerciseJsonUtil.parseJson(content, GenerateExamResponse.class);
        //进行转换
        List<GenerateExamVO> generateExamVOList = generateExamResponseList.stream().map(generateExamResponse -> {
            GenerateExamVO generateExamVO = new GenerateExamVO();
            BeanUtil.copyProperties(generateExamResponse, generateExamVO);
            //主键回显
            if(generateExam.getId()!=null) {
                generateExamVO.setId(generateExam.getId());
            }
            return generateExamVO;
        }).toList();
        //json化
        content = toJsonStr(generateExamVOList);
        //存已经转换好的题目数据 ，而不是每次查询，再来一次转换？
        generateExam.setContent(content);
        boolean save = this.saveOrUpdate(generateExam);
        if(!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,SYSTEM_ERROR);
        }
        return generateExamVOList;
    }
    @Override
    public List<GenerateExamVO> addGenerateExamAsy(AddGenerateExamRequest addGenerateExamRequest, User user) {
        //1.1 生成测试Id  已改为 前端上传文件直接解析
//        Long id = addGenerateExamRequest.getId();
        Long id = 1L;//保证不报错
        //大纲id
        Long generateTeachId = addGenerateExamRequest.getGenerateTeachId();
        //知识点
        String knowledgePoint = addGenerateExamRequest.getKnowledgePoint();
        AddGenerateExamForAiRequest addGenerateExamForAiRequest = new AddGenerateExamForAiRequest();
        if(ObjUtil.isNotNull(id)){
            //则选择的是自主提供的参考材料
            GenerateExam generateExam = this.getById(id);
            String reference = generateExam.getReference();
            //设置参考材料
            addGenerateExamForAiRequest.setReference(reference);
        }
        //判断是根据什么来生成测试
        if(generateTeachId !=null){
            GenerateTeach generateTeach = generateTeachService.getById(generateTeachId);
            //选择的是已有的课程大纲
            String courseOutline = generateTeach.getContent();
            if(addGenerateExamForAiRequest.getReference()!=null&&"".equals(addGenerateExamForAiRequest.getReference())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(courseOutline);
        }
        if(knowledgePoint !=null){
            //选择的是知识点
            if(addGenerateExamForAiRequest.getReference()!=null&&"".equals(addGenerateExamForAiRequest.getReference())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,ONLY_ONE_REFERENCE_ALLOWED);
            }
            addGenerateExamForAiRequest.setReference(knowledgePoint);
        }
        addGenerateExamForAiRequest.setExams(addGenerateExamRequest.getExams());
        addGenerateExamForAiRequest.setDifficultyLevel(addGenerateExamRequest.getDifficultyLevel());
        String chatId = UUID.randomUUID().toString();
        String content = examGenerateApp.doGenerate(addGenerateExamForAiRequest, chatId);

        //入库数据
        GenerateExam generateExam = new GenerateExam();
        generateExam.setId(id);
        String title = user.getUserName() + "的教学测试";//标题
        generateExam.setTitle(title);
//        generateExam.setContent(content);
        generateExam.setUserId(user.getId());
        generateExam.setGenerateTeachId(generateTeachId);
        generateExam.setKnowledgePoint(knowledgePoint);
        generateExam.setDifficultyLevel(addGenerateExamRequest.getDifficultyLevel());
        generateExam.setStatus(1);//草稿

        //解析content 成为一个数组列表
        List<GenerateExamResponse> generateExamResponseList = parseGenerateExerciseJsonUtil.parseJson(content, GenerateExamResponse.class);
        //进行转换
        List<GenerateExamVO> generateExamVOList = generateExamResponseList.stream().map(generateExamResponse -> {
            GenerateExamVO generateExamVO = new GenerateExamVO();
            BeanUtil.copyProperties(generateExamResponse, generateExamVO);
            //主键回显
            if(generateExam.getId()!=null) {
                generateExamVO.setId(generateExam.getId());
            }
            return generateExamVO;
        }).toList();
        //json化
        content = toJsonStr(generateExamVOList);
        //存已经转换好的题目数据 ，而不是每次查询，再来一次转换？
        generateExam.setContent(content);
        boolean save = this.saveOrUpdate(generateExam);
        if(!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,SYSTEM_ERROR);
        }
        return generateExamVOList;
    }

    @Override
    public QueryWrapper<GenerateExam> getGenerateExamQueryWrapper(GenerateExamQueryDTO generateExamQueryDTO) {
        //获取查询条件
        String title = generateExamQueryDTO.getTitle();
        Long userId = generateExamQueryDTO.getUserId();
        String knowledgePoint = generateExamQueryDTO.getKnowledgePoint();
        Long id = generateExamQueryDTO.getId();
        String sortField = generateExamQueryDTO.getSortField();
        String sortOrder = generateExamQueryDTO.getSortOrder();
        //构造queryMapper
        QueryWrapper<GenerateExam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotNull(userId), "userId", userId);
        queryWrapper.eq(StrUtil.isNotBlank(title), "title", title);
        queryWrapper.eq(StrUtil.isNotBlank(knowledgePoint), "knowledgePoint", knowledgePoint);
        queryWrapper.orderBy(StrUtil.isNotBlank(sortField), OrderConstant.ASC.equals(sortOrder), sortField);
        //返回query对象
        return queryWrapper;
    }

    @Override
    public List<GenerateExamPageVO> getGenerateExamVOList(List<GenerateExam> records) {
        return records.stream().map(this::getGenerateExamPageVO).collect(Collectors.toList());
    }

    @Override
    public GenerateExamPageVO getGenerateExamPageVO(GenerateExam generateExam) {
        GenerateExamPageVO generateExamPageVO = new GenerateExamPageVO();
        BeanUtils.copyProperties(generateExam, generateExamPageVO);
        return generateExamPageVO;
    }

    @Override
    public List<GenerateExamVO> getGenerateExamVO(GenerateExam generateExam) {
        String content = generateExam.getContent();
        String title = generateExam.getTitle();
        List<GenerateExamVO> generateExamVOS = parseGenerateExerciseJsonUtil.parseJson(content, GenerateExamVO.class);
        generateExamVOS.forEach(generateExamVO -> {
            generateExamVO.setTitle(title);
        });
        return generateExamVOS;
    }
}




